package com.googlecode.uipipedream;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.googlecode.uipipedream.impl.ColourPanel;
import com.googlecode.uipipedream.impl.ComplementaryHorizontalSliderBar;
import com.googlecode.uipipedream.impl.HorizontalSliderBar;
import com.googlecode.uipipedream.impl.VerticalSliderBar;
import com.googlecode.uipipedream.spec.ColourModel;
import com.googlecode.uipipedream.spec.HSBType;

/**
 * <p>
 * This program (UIPipeDream) is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * </p>
 * 
 * <p>
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * </p>
 * 
 * <p>
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <a
 * href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>.
 * </p>
 * 
 * @author <a href="http://daemonsadvocate.blogspot.com/">Matthew B. Gray</a>
 * @author James Jones
 * @version 1.0 Final
 */
class SpecifyNColours extends JSlider {
	private static final long serialVersionUID = 3248353067778612269L;
	final static int lowerBound = 1;
	final static int upperBound = 17;
	final SpecifyNColours thisObj = this;

	public SpecifyNColours(final ColourModel model) {
		super(new DefaultBoundedRangeModel(model.getNColours(), 2, lowerBound,
				upperBound));
		this.setOrientation(SwingConstants.VERTICAL);
		this.setBackground(Color.black);

		this.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				int value = thisObj.getValue();
				model.setNColours(value);
				if (value != model.getNColours())
					thisObj.setValue(model.getNColours());
			}
		});
	}
}

class ColourPallet extends Canvas {
	private ColourModel model;
	private Dimension d;
	private Image drawing;
	protected Graphics graphics = null;

	public ColourPallet(ColourModel model) {
		this.model = model;
	}

	@Override
	public void update(Graphics g) {
		paint(g);
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);

		// 1. Setup variables
		this.d = getSize();
		this.drawing = createImage(d.width, d.height);
		this.graphics = this.drawing.getGraphics();

		// 2. Clear image
		graphics.setColor(getBackground());
		graphics.fillRect(0, 0, d.width, d.height);
		graphics.setColor(Color.black);

		// 3. Draw pallet
		// switch(model.getType()) {
		// case ANALOGUS:
		float[] hues = model.getAnalogusHues();
		int individualWidth = d.width / hues.length;
		int padding = (int) (individualWidth * 0.05);

		for (int i = 0; i < hues.length; i++) {
			Color c = Color.getHSBColor(hues[i], model.getSaturation(), model
					.getBrightness());
			int x = individualWidth * i + padding;
			graphics.setColor(c);
			graphics.drawRect(x, padding, individualWidth - 2 * padding,
					d.height - individualWidth * 2);
		}
		// break;
		//			
		// case COMPLEMENTARY:
		//			
		// break;
		//			
		// case SPLIT_COMPLEMENTARY:
		//			
		// break;
		//			
		// default:
		//			
		// }

		g.drawImage(drawing, 0, 0, this);
	}

}

public class Main extends JFrame implements Runnable {
	private static final long serialVersionUID = 2880337302963035000L;
	private ColourModel model = new ColourModel();
	private ColourPanel colourPanel;

	/**
	 * @see {@link #run()}
	 */
	public static void main(String[] args) {
		// Pass this object as a thread onto the AWT managed event queue. See
		// run().
		java.awt.EventQueue.invokeLater(new Main());
	}

	// @SuppressWarnings("deprecation")
	// public boolean mouseDown(Event e, int x, int y) {
	// if (colourPanel.getBounds().contains(x, y)) {
	// Container f = this;
	// while (f != null && !(f instanceof Frame))
	// f = f.getParent();
	// if (f != null)
	// ((Frame) f).setCursor(Frame.CROSSHAIR_CURSOR);
	// return true;
	// } else
	//
	// return false;
	// }

	/**
	 * @see Main#main(String[])
	 */
	@Override
	public void run() {
		// 1. Setup how this window looks and acts.
		this.setTitle("A Novel Colour Selector");
		this.setMinimumSize(new Dimension(400, 200));
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

		// 2. Setup components.
		this.getContentPane().setBackground(Color.black);
		this.colourPanel = new ColourPanel(model);

		// 3. Setup internal component layouts.
		final JPanel saturationBrightnessTweekers = new JPanel();
		saturationBrightnessTweekers.setLayout(new GridLayout(2, 2));
		saturationBrightnessTweekers.setBackground(Color.black);
		saturationBrightnessTweekers.add(new JLabel("Saturation"));
		saturationBrightnessTweekers.add(new VerticalSliderBar(model,
				HSBType.SATURATION));
		saturationBrightnessTweekers.add(new JLabel("Brightness"));
		saturationBrightnessTweekers.add(new VerticalSliderBar(model,
				HSBType.BRIGHTNESS));

		final JPanel hueSelectorPanel = new JPanel();
		hueSelectorPanel.setLayout(new GridLayout(2, 1));
		hueSelectorPanel.setBackground(Color.black);
		hueSelectorPanel.add(new HorizontalSliderBar(model, HSBType.HUE));
		hueSelectorPanel.add(new ComplementaryHorizontalSliderBar(model,
				HSBType.HUE));

		final JPanel exportTools = new JPanel();
		exportTools.setLayout(new GridLayout(3, 1));

		final JButton analogus = new JButton("Export analogus colours");
		final JButton complementary = new JButton(
				"Export Plain-Jane complementary colours");
		final JButton splitComplementary = new JButton(
				"Export split complements");

		analogus.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				chooser.showDialog(analogus, "Okay Button");
				File file = chooser.getSelectedFile();
				try {
					if (file != null)
						CSSGenerator.generateCSS(file, model
								.exportAnalogusColours());
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		complementary.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				chooser.showDialog(analogus, "Okay Button");
				File file = chooser.getSelectedFile();
				try {
					if (file != null)
						CSSGenerator.generateCSS(file, model
								.exportComplementaryColour());
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});
		splitComplementary.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				chooser.showDialog(analogus, "Okay Button");
				File file = chooser.getSelectedFile();
				try {
					if (file != null)
						CSSGenerator.generateCSS(file, model
								.exportSplitComplementaryColours());
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		});

		exportTools.add(analogus);
		exportTools.add(complementary);
		exportTools.add(splitComplementary);

		// 4. Add component layouts to the window.
		this.setLayout(new BorderLayout());
		this.add("Center", new SpecifyNColours(model));
		this.add("West", hueSelectorPanel);
		this.add("East", saturationBrightnessTweekers);
		this.add("South", exportTools);

		// 5. Set inital colours
		this.model.setBrightness(1f);
		this.model.setSaturation(1f);
		this.model.setColor(Color.red);
		this.validate();

		// 6. Display the window and start this application.
		this.setLocation(100, 100);
		this.pack();
		this.setVisible(true);
	}
}
